// ListCtrlDemo.cpp : main source file for ListCtrlDemo.exe
//

#include "stdafx.h"

#include <atlframe.h>
#include <atlctrls.h>
#include <atldlgs.h>

#include "resource.h"
#include "MainDlg.h"

LPCTSTR CMigrationDialog::CDataRateComboBox::m_texts[] = { _T("38.4kbps"), _T("19.2kbps"), _T("9.6kbps"), _T("4.8kbps")/*, _T("2.4kbps")*/};
U8 CMigrationDialog::CDataRateComboBox::m_values[]={8, 16, 35, 71/*, 17+128*/};
LPCTSTR CMigrationDialog::CResponseComboBox::m_texts[] = {_T("within 9 sec"), _T("within 7 sec"), _T("within 5 sec"), _T("within 4 sec"),  _T("within 3.5 sec"), 
					_T("within 3 sec"),_T("within 2.5 sec"), _T("within 2 sec")};
U8 CMigrationDialog::CResponseComboBox::m_values[]={255, 200, 142, 114, 96, 85, 71, 57};
LPCTSTR g_PP_URL = _T("http://www.caogadgets.com/about/private-policy.aspx");
int CSlaveProfile::Delay_Index2Seconds[] = {0, 30, 60, 120, 300, 600, 900, 1800, 3600, 7200};
double CSlaveProfile::Angle_Index2Radian[] = 
{3.1415926/180.0*5.0,3.1415926/180.0*10.0, 3.1415926/180.0*15.0, 3.1415926/180.0*22.5, 
3.1415926/180.0*30.0,3.1415926/180.0*45.0, 3.1415926/180.0*60.0, 3.1415926/180.0*75.0, 3.1415926/180.0*90.0};

void _cdecl MyTrace(const TCHAR *pszFormat, ...)
{
	va_list ptr;
	va_start(ptr, pszFormat);

	static const int nCount = 1024;
	TCHAR szBuf[nCount] = {'\0'};

	wvnsprintf( szBuf, nCount, pszFormat, ptr);
	szBuf[nCount-1] = 0;

	OutputDebugString(szBuf);

	va_end(ptr);
}

class CLauncherDialog : public CDialogImpl<CLauncherDialog>
{
public:
	enum { IDD = IDD_LAUNCHERHIDDEN };

	BEGIN_MSG_MAP(thisClass)
		MESSAGE_HANDLER(WM_WINDOWPOSCHANGING, OnWndPosChanging)
		MESSAGE_HANDLER(WM_INITDIALOG, OnInitDialog)
		COMMAND_ID_HANDLER(IDOK, OnOK)
		COMMAND_ID_HANDLER(IDCANCEL, OnCancel)
		COMMAND_ID_HANDLER(IDC_QUIT_FOR_UPDATE, OnQuitForUpdate)
		MESSAGE_HANDLER(WM_CLOSE, OnClose)
		MESSAGE_HANDLER(WM_DEVICECHANGE, OnDeviceChange)
		
	END_MSG_MAP()
	
	LRESULT OnQuitForUpdate(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
	{
		EndDialog(IDC_QUIT_FOR_UPDATE);
		return 0;
	}

	LRESULT OnClose(UINT /*uMsg*/, WPARAM wParam, LPARAM lParam, BOOL& /*bHandled*/)
	{
		EndDialog(0);
		return 0;
	}

	LRESULT OnDeviceChange(UINT /*uMsg*/, WPARAM wParam, LPARAM lParam, BOOL& /*bHandled*/)
	{
		if((int)wParam == DBT_DEVICEARRIVAL )
		{
			DEV_BROADCAST_HDR* pHdr = (DEV_BROADCAST_HDR*)lParam;
			if(pHdr)
			{
				if(pHdr->dbch_devicetype == DBT_DEVTYP_VOLUME)
				{
					ATL::CRegKey reg;
					LONG result = reg.Open(HKEY_CURRENT_USER, g_regkey);
					if(result != ERROR_SUCCESS)
					{
						return 0;
					}
					else
					{
						DWORD val=1;
						if(ERROR_SUCCESS != reg.QueryDWORDValue(_T("autoOpen"), val))
						{
							return 0;
						}
						else{
							if(val==0){
								EndDialog(0);
								return 0;
							}
						}
					}	


					DEV_BROADCAST_VOLUME* pVol = (DEV_BROADCAST_VOLUME*)pHdr;

					for(int i=0;i<26;i++){
						if((pVol->dbcv_unitmask)>>i & 0x1){
							CString ini_fn;
							ini_fn.Format(_T("%c:\\"), _T('A')+i);
							CString volume_name; 
							DWORD maxlen, flags;
							GetVolumeInformation(ini_fn, volume_name.GetBuffer(MAX_PATH+1), MAX_PATH+1, NULL, &maxlen, &flags,NULL,0);
							volume_name.ReleaseBuffer();
							if(volume_name.Compare(_T("Tag Manager"))==0){
								ini_fn.Append(_T("WirelessTagManager.exe.data"));
								
								
								CString thisExe; 
								GetModuleFileName(NULL, thisExe.GetBuffer(1024),1019);
								thisExe.ReleaseBuffer();
								CString cmdline; 
								cmdline.Format(_T("\"%s\" /Data %s"), thisExe, ini_fn.GetString());
								//cmdline.Format(_T("\"%s\""), thisExe);
								
								//ShellExecute(m_hWnd, _T("open"), thisExe, cmdline, NULL, SW_SHOWNORMAL);
								STARTUPINFO si;
								PROCESS_INFORMATION pi;
								ZeroMemory( &si, sizeof(si) );
								si.cb = sizeof(si);
								si.wShowWindow = SW_SHOW;
								si.dwFlags=STARTF_USESHOWWINDOW;
								ZeroMemory( &pi, sizeof(pi) );
								CreateProcess(thisExe, cmdline.GetBuffer(), NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi);
								CloseHandle( pi.hProcess );
								CloseHandle( pi.hThread );
								
								break;
							}

						}
					}
				}
			}
		}
		return 0;
	}

	CLauncherDialog()
	{	
	}

	LRESULT OnOK(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
	{
		EndDialog(1);
		return 0;
	}

	LRESULT OnCancel(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
	{
		EndDialog(0);
		return 0;
	}

	LRESULT OnWndPosChanging(UINT /*uMsg*/, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
	{
		((WINDOWPOS*)lParam)->flags = SWP_HIDEWINDOW;
		bHandled=TRUE;
		//ShowWindow(SW_HIDE);
		return 0;
	}
	LRESULT OnInitDialog(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
	{
		SetWindowText(g_LauncherMutexName);
		ShowWindow(SW_HIDE);
		return TRUE;
	}
};

//#ifdef REGISTER_INSTANCE

void RegisterRestartInstanceInRegistry(LPCTSTR cmdline){
	ATL::CRegKey reg;
	CString key;
	key.Format(_T("PID%x"), GetCurrentProcessId());
	CString thisExe; 
	GetModuleFileName(NULL, thisExe.GetBuffer(MAX_PATH+1),MAX_PATH);
	thisExe.ReleaseBuffer();

	LONG result = reg.Open(HKEY_CURRENT_USER, g_regkey_instances);
	if(result != ERROR_SUCCESS)
	{
		result = reg.Create(HKEY_CURRENT_USER, g_regkey_instances);
	}
	if(result == ERROR_SUCCESS)
	{
		reg.SetStringValue(key, thisExe);
		reg.Close();
	}

	result = reg.Open(HKEY_CURRENT_USER, g_regkey_cmdlines);
	if(result != ERROR_SUCCESS)
	{
		result = reg.Create(HKEY_CURRENT_USER, g_regkey_cmdlines);
	}
	if(result == ERROR_SUCCESS)
	{
		reg.SetStringValue(key, cmdline);
		reg.Close();
	}
}
/*
void UnregisterInstanceInRegistry()
{
	ATL::CRegKey reg;
	CString key;
	key.Format(_T("PID%x"), GetCurrentProcessId());
	reg.Open(HKEY_CURRENT_USER, g_regkey_instances);
	reg.DeleteValue(key);
	reg.Close();
	reg.Open(HKEY_CURRENT_USER, g_regkey_cmdlines);
	reg.DeleteValue(key);
	reg.Close();
}
#else

#define RegisterInstanceInRegistry(x) __noop
#define UnregisterInstanceInRegistry() __noop

#endif
*/
CAppModule _Module;
int WINAPI _tWinMain(HINSTANCE hInstance, HINSTANCE /*hPrevInstance*/, LPTSTR lpstrCmdLine, int nCmdShow)
{

	HRESULT hRes = ::OleInitialize(NULL);
// If you are running on NT 4.0 or higher you can use the following call instead to 
// make the EXE free threaded. This means that calls come in on a random RPC thread.
//	HRESULT hRes = ::CoInitializeEx(NULL, COINIT_MULTITHREADED);
	ATLASSERT(SUCCEEDED(hRes));

	// this resolves ATL window thunking problem when Microsoft Layer for Unicode (MSLU) is used
	::DefWindowProc(NULL, 0, 0, 0L);

	/*AtlInitCommonControls(
		ICC_WIN95_CLASSES |
		ICC_DATE_CLASSES |
		ICC_USEREX_CLASSES |
		ICC_COOL_CLASSES |
		ICC_PAGESCROLLER_CLASS |
		ICC_NATIVEFNTCTL_CLASS);*/

	AtlInitCommonControls(ICC_COOL_CLASSES | ICC_BAR_CLASSES);	// add flags to support other controls

	hRes = _Module.Init(NULL, hInstance);
	ATLASSERT(SUCCEEDED(hRes));

	WNDCLASS wc;
	::GetClassInfo(hInstance, _T("#32770"), &wc);
	wc.lpszClassName = _T("WirelessTagManagerClass");
	RegisterClass(&wc);	

	int nRet = 0;
	CString ini_fn;

	TCHAR szTokens[] = _T("-/");

	LPCTSTR lpszToken = CAtlModule::FindOneOf(lpstrCmdLine, szTokens);
	while (lpszToken != NULL)
	{
		if (CAtlModule::WordCmpI(lpszToken, _T("Data"))==0)
		{
			ini_fn = CAtlModule::FindOneOf(lpszToken, _T(" \t"));
			break;
		}
		else if (CAtlModule::WordCmpI(lpszToken, _T("Launcher"))==0)
		{
			HANDLE hMutexOneInstance = ::CreateMutex( NULL, TRUE, g_LauncherMutexName); 
			if (GetLastError() != ERROR_ALREADY_EXISTS)
			{
				CLauncherDialog dlg;
				if(IDC_QUIT_FOR_UPDATE == dlg.DoModal())
					RegisterRestartInstanceInRegistry(lpstrCmdLine);
			}
			ReleaseMutex(hMutexOneInstance); 
			CloseHandle(hMutexOneInstance);	
			goto _exit;
		}
		else if (CAtlModule::WordCmpI(lpszToken, _T("Update"))==0)
		{
			/*MessageBox(NULL,_T("To complete update, please close the current Wireless Tag Manager window. Click Cancel to cancel update. "), 
							_T("Wireless Tag Manager Updater"), MB_ICONWARNING|MB_OKCANCEL|MB_SETFOREGROUND);
			ATLASSERT(FALSE);
			*/
			std::set<CString> target_locations;
			std::map<CString, CString> run_exe, run_args;

			ATL::CRegKey reg; 
			LONG result = reg.Open(HKEY_CURRENT_USER, g_regkey_instances);
			if(result == ERROR_SUCCESS)
			{
				while(1){
					CString pid, exeName;
					DWORD pid_len=256, exeName_len = MAX_PATH;
					if(ERROR_NO_MORE_ITEMS==
						RegEnumValue(reg.m_hKey, 0, pid.GetBuffer(pid_len), &pid_len, NULL, NULL,(BYTE*)exeName.GetBuffer(exeName_len), &exeName_len))break;
					exeName.ReleaseBuffer();
					pid.ReleaseBuffer();
					target_locations.insert(exeName);
					run_exe.insert( std::pair<CString, CString>(pid, exeName));
					reg.DeleteValue(pid.GetString());
				}
				reg.Close();
			}

			result = reg.Open(HKEY_CURRENT_USER, g_regkey_cmdlines);
			if(result == ERROR_SUCCESS)
			{
				while(1){
					CString pid, args;
					DWORD pid_len=256, args_len = MAX_PATH;
					if(ERROR_NO_MORE_ITEMS==
						RegEnumValue(reg.m_hKey, 0, pid.GetBuffer(pid_len), &pid_len, NULL, NULL, (BYTE*)args.GetBuffer(args_len), &args_len))break;
					args.ReleaseBuffer();
					pid.ReleaseBuffer();
					run_args.insert( std::pair<CString, CString>(pid, args));
					reg.DeleteValue(pid.GetString());
				}
				reg.Close();
			}

			CString thisExe; 
			GetModuleFileName(NULL, thisExe.GetBuffer(1024),1019);
			thisExe.ReleaseBuffer();

			thisExe.AppendChar(0);

			for(std::set<CString>::iterator i = target_locations.begin(); i!=target_locations.end(); i++){	

				CString target_file = *i;
				CString target_dir= *i;
				int last_yen = i->ReverseFind(_T('\\'))+1;
				target_dir.SetAt(last_yen, 0);
				target_dir.SetAt(last_yen+1, 0);
									
				while(1){
					int b=3;

					while(b--){
						Sleep(500);

						if(!DeleteFile(target_file))continue;

						CopyFile(thisExe, target_file, FALSE);

						/*SHFILEOPSTRUCT sp;
						ZeroMemory(&sp, sizeof(sp));
						sp.wFunc=FO_COPY;
						
						sp.pFrom=thisExe;

						sp.pTo=target_dir;
						sp.fFlags=FOF_NOCONFIRMATION|FOF_SIMPLEPROGRESS|FOF_NOCONFIRMMKDIR;
						sp.lpszProgressTitle=_T("Updating WirelessTagManager.exe ...");
						if(0==SHFileOperation(&sp))break;
						*/
					}
					if(b==0){
						if(IDCANCEL == MessageBox(NULL,_T("To complete update, please close the current Wireless Tag Manager window. Click Cancel to cancel update. "), 
							_T("Wireless Tag Manager Updater"), MB_ICONWARNING|MB_OKCANCEL|MB_SETFOREGROUND))
							break;
					}else
						break;
				}
			}

			for(std::map<CString, CString>::iterator i = run_exe.begin(); i!=run_exe.end(); i++){	
				CString cmdline;
				cmdline.Format(_T("\"%s\" %s"), i->second.GetString(), run_args[i->first].GetString());

				STARTUPINFO si;
				PROCESS_INFORMATION pi;
				ZeroMemory( &si, sizeof(si) );
				si.cb = sizeof(si);
				ZeroMemory( &pi, sizeof(pi) );
				CreateProcess(i->second.GetString(), cmdline.GetBuffer(), NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi);
				CloseHandle( pi.hProcess );
				CloseHandle( pi.hThread );

			}
			//::ShellExecute(NULL, _T("open"), target, NULL, NULL, SW_SHOWNORMAL);

			MoveFileEx(thisExe, NULL, MOVEFILE_DELAY_UNTIL_REBOOT);
			goto _exit;
		}
		
		lpszToken = CAtlModule::FindOneOf(lpszToken, szTokens);
	}

	// BLOCK: Run application
	{	
		CMainDlg dlgMain(ini_fn);
		nRet = dlgMain.DoModal();
		if(nRet==IDC_QUIT_FOR_UPDATE)
			RegisterRestartInstanceInRegistry(lpstrCmdLine);
	}

_exit:

	_Module.Term();
	::OleUninitialize();

	return nRet;
}
